/**
在 Webpack 中，压缩 JavaScript 和 CSS 文件是优化构建输出的重要步骤，可以显著减小文件体积，从而提高网页加载速度和性能。以下是关于 Webpack 中 JS 和 CSS 文件压缩的说明总结：
  1. 为什么要压缩文件？
  - 减小文件体积: 压缩可以去掉不必要的空格、注释、换行等，从而减小文件的大小。
  - 提高加载速度: 更小的文件体积意味着更快的下载速度，尤其是在网络条件较差的情况下。
  - 优化用户体验: 更快的加载时间可以提升用户体验，降低用户流失率。

  2. JavaScript 压缩
  在 Webpack 中，JavaScript 文件的压缩通常通过 `TerserPlugin` 实现。`TerserPlugin` 是一个用于压缩和混淆 JavaScript 代码的插件。

  安装 TerserPlugin
  在 Webpack 5 及以上版本中，`TerserPlugin` 默认已经包含在内。如果是使用较旧版本，可以通过以下命令安装：


  ```bash
  npm install --save-dev terser-webpack-plugin
  ```

  配置 Webpack
  在 Webpack 配置文件中，可以通过 `optimization` 属性来配置 JavaScript 压缩。

  ```javascript
  const path = require('path');

  module.exports = {
      entry: './src/index.js',
      output: {
          filename: 'bundle.js',
          path: path.resolve(__dirname, 'dist'),
      },
      optimization: {
          minimize: true, // 启用压缩
          minimizer: [
              new TerserPlugin({
                  terserOptions: {
                      compress: {
                          dropConsole: true, // 删除 console.log
                      },
                  },
              }),
          ],
      },
      mode: 'production', // 设置为生产模式
  };
  ```

  3. CSS 压缩
  CSS 文件的压缩通常使用 `css-minimizer-webpack-plugin` 插件。该插件可以有效地压缩 CSS 文件。

  安装 css-minimizer-webpack-plugin
  通过以下命令安装：

  ```bash
  npm install --save-dev css-minimizer-webpack-plugin
  ```

  配置 Webpack
  在 Webpack 配置文件中，可以通过 `optimization` 属性来配置 CSS 压缩。

  ```javascript
  const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

  module.exports = {
      entry: './src/index.js',
      output: {
          filename: 'bundle.js',
          path: path.resolve(__dirname, 'dist'),
      },
      module: {
          rules: [
              {
                  test: /\.css$/,
                  use: [
                      MiniCssExtractPlugin.loader,
                      'css-loader',
                  ],
              },
          ],
      },
      optimization: {
          minimize: true, // 启用压缩
          minimizer: [
              new TerserPlugin(), // JS 压缩
              new CssMinimizerPlugin(), // CSS 压缩
          ],
      },
      plugins: [
          new MiniCssExtractPlugin({
              filename: 'styles.css', // 提取的 CSS 文件名
          }),
      ],
      mode: 'production', // 设置为生产模式
  };
  ```

  4. 注意事项
  - 生产模式: 压缩通常在生产模式下进行。在开发模式下，建议保留未压缩的代码以便调试。
  - 性能: 压缩可能会增加构建时间，尤其是在大型项目中，因此需要在构建时间和文件大小之间找到平衡。
  - 错误检查: 在压缩过程中，确保代码没有语法错误，以避免压缩失败。

  总结
  在 Webpack 中，通过使用 `TerserPlugin` 和 `css-minimizer-webpack-plugin` 可以有效地压缩 JavaScript 和 CSS 文件，从而减小文件体积，提高加载速度和用户体验。合理配置压缩选项，可以在保证代码质量的前提下，优化应用的性能。希望这个总结对你理解 Webpack 中 JS 和 CSS 文件压缩的过程有所帮助！
 */
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { ProvidePlugin } = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: "production",
  devtool: false,
  entry: "./src/main.js",
  output: {
    clean: true,
    path: path.resolve(__dirname, "./build"),
    filename: "js/[name]_chunk.js",
    chunkFilename: "js/[name]_chunk.js", // 代码分割的文件名
  },
  /**
   * externals: 排除某些包不需要进行打包
   */
  // externals: {
  //   /**
  //    * key属性名: 排除的框架名称
  //    * value属性值: 从CDN地址请求下来的js中提供对应的名称
  //    */
  //   react: "React",
  //   axios: "axios",
  // },
  /**
   * resolve: 配置模块解析
   * extensions: 配置解析模块时自动补全的扩展名
   */
  resolve: {
    extensions: [".js", ".json", ".wasm", ".jsx", ".ts"],
  },
  devServer: {
    static: ["public", "content"],
    port: 3000,
    compress: true,
    proxy: [
      {
        context: () => true,
        target: "http://localhost:1234",
        pathRewrite: { "^/api": "" },
      },
    ],
    historyApiFallback: true,
  },
  optimization: {
    chunkIds: "deterministic", // 生成文件名时使用确定的文件名
    runtimeChunk: {
      name: "runtime", // 将runtime相关的代码单独打包
    },
    splitChunks: {
      // 分包配置
      chunks: "all", // 对所有模块都进行分割
      minSize: 10, // 分割的模块最小为10kb
      // 自己对需要进行拆包的内容进行分包
      cacheGroups: {
        utils: {
          test: /utils/,
          filename: "js/[id]_utils.js",
        },
        vendors: {
          // /node_modules/
          // window上面 /\
          // mac上面 /
          test: /[\\/]node_modules[\\/]/,
          filename: "js/[id]_vendors.js",
        },
      },
    },
    // 压缩配置
    minimizer: [
      new TerserPlugin({
        extractComments: false, // 不将注释提取到单独的文件中
      }),
    ],
  },
  module: {
    rules: [
      {
        test: /\.jsx$/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.js$/,
        use: "babel-loader",
      },
      {
        test: /\.css$/,
        use: [
          // 'style-loader' // 将css文件变成style标签插入到html文件中, 开发阶段
          MiniCssExtractPlugin.loader, // 将css文件变成style标签插入到html文件中, 生产阶段
          "css-loader", // 将css文件变成commonjs模块加载到js文件中
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.html", // 模板文件
    }),
    new ProvidePlugin({
      axios: ["axios", "default"],
      dayjs: "dayjs",
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
      chunkFilename: "css/[name]_chunk.css",
    }),
  ],
};
